  localparam NUM_CE = 4;  // Must be no more than 10 (6 ports taken by transport and IO connected CEs)

  wire [NUM_CE*64-1:0] ce_flat_o_tdata, ce_flat_i_tdata;
  wire [63:0]          ce_o_tdata[0:NUM_CE-1], ce_i_tdata[0:NUM_CE-1];
  wire [NUM_CE-1:0]    ce_o_tlast, ce_o_tvalid, ce_o_tready, ce_i_tlast, ce_i_tvalid, ce_i_tready;
  wire [63:0]          ce_debug[0:NUM_CE-1];

  // Flatten CE tdata arrays
  genvar k;
  generate
    for (k = 0; k < NUM_CE; k = k + 1) begin
      assign ce_o_tdata[k] = ce_flat_o_tdata[k*64+63:k*64];
      assign ce_flat_i_tdata[k*64+63:k*64] = ce_i_tdata[k];
    end
  endgenerate
  
  wire [63:0] afp0_tx_tdata;
  wire [3:0]  afp0_tx_tuser;
  wire        afp0_tx_tlast;
  wire        afp0_tx_tvalid;
  wire        afp0_tx_tready;
  
  // SFP+ 0 data stream
  wire [63:0] xfp0_tx_tdata;
  wire [3:0]  xfp0_tx_tuser;
  wire        xfp0_tx_tlast;
  wire        xfp0_tx_tvalid;
  wire        xfp0_tx_tready;

  wire [63:0] afp0_rx_tdata  ;
  wire [3:0]  afp0_rx_tuser  ;
  wire        afp0_rx_tlast  ;
  wire        afp0_rx_tvalid ;
  wire        afp0_rx_tready ;

  // SFP+ 0 data stream
  wire [63:0] yfp0_rx_tdata;
  wire [3:0]  yfp0_rx_tuser;
  wire        yfp0_rx_tlast;
  wire        yfp0_rx_tvalid;
  wire        yfp0_rx_tready;

  assign afp0_tx_tuser  = 'b0;
  assign ce_i_tdata[0]  = xfp0_tx_tdata ;
  assign ce_i_tlast[0]  = xfp0_tx_tlast ; 
  assign ce_i_tvalid[0] = xfp0_tx_tvalid; 
  assign xfp0_tx_tready = ce_i_tready[0] ;

  assign yfp0_rx_tuser  = 'b0;
  assign yfp0_rx_tdata  = ce_o_tdata[2];
  assign yfp0_rx_tlast  = ce_o_tlast[2];
  assign yfp0_rx_tvalid = ce_o_tvalid[2];
  assign ce_o_tready[2] = yfp0_rx_tready;

  x310_fc16_amp #( .TCLK_DIV ( 199 ) )
  x310_fc16_amp_inst0 ( 

   .bus_clk(bus_clk), .bus_rst(bus_rst), 

   .tx_tdata (afp0_tx_tdata),  .tx_tuser (afp0_tx_tuser), .tx_tlast(afp0_tx_tlast), .tx_tvalid(afp0_tx_tvalid), .tx_tready(afp0_tx_tready),
   .rx_tdata (xfp0_tx_tdata),  .rx_tuser (xfp0_tx_tuser), .rx_tlast(xfp0_tx_tlast), .rx_tvalid(xfp0_tx_tvalid), .rx_tready(xfp0_tx_tready),

   .dbg_tag_clk ( dbg_tag_clk ),
   .dbg_tag_tx  ( dbg_tag_tx  ),
   .dbg_tag_rx  ( dbg_tag_rx  )
  );      

  x310_fc16_tx #( .TCLK_DIV ( 199 ) )
  x310_fc16_tx_inst0 ( 
    
    .bus_clk(bus_clk), .bus_rst(bus_rst), 

    .tx_tdata (yfp0_rx_tdata),  .tx_tuser (yfp0_rx_tuser), .tx_tlast(yfp0_rx_tlast), .tx_tvalid(yfp0_rx_tvalid), .tx_tready(yfp0_rx_tready),
    .rx_tdata (afp0_rx_tdata),  .rx_tuser (afp0_rx_tuser), .rx_tlast(afp0_rx_tlast), .rx_tvalid(afp0_rx_tvalid), .rx_tready(afp0_rx_tready),

    .dbg_tag_tx     ( dbg_tag_tx ),
    .dbg_tag_tx_dly ( dbg_tag_tx_dly )
  );   

  noc_block_ddc #( .NUM_CHAINS(2), .NUM_HB(3), .CIC_MAX_DECIM(255)) inst_noc_block_ddc_0 (
    .bus_clk(bus_clk), .bus_rst(bus_rst),
    .ce_clk(ce_clk), .ce_rst(ce_rst),
    .i_tdata(ce_o_tdata[0]), .i_tlast(ce_o_tlast[0]), .i_tvalid(ce_o_tvalid[0]), .i_tready(ce_o_tready[0]),
    //.o_tdata(ce_i_tdata[0]), .o_tlast(ce_i_tlast[0]), .o_tvalid(ce_i_tvalid[0]), .o_tready(ce_i_tready[0]),
    .o_tdata(afp0_tx_tdata), .o_tlast(afp0_tx_tlast), .o_tvalid(afp0_tx_tvalid), .o_tready(afp0_tx_tready),
    .debug(ce_debug[0]));

  noc_block_ddc #( .NUM_CHAINS(2), .NUM_HB(3), .CIC_MAX_DECIM(255)) inst_noc_block_ddc_1 (
    .bus_clk(bus_clk), .bus_rst(bus_rst),
    .ce_clk(ce_clk), .ce_rst(ce_rst),
    .i_tdata(ce_o_tdata[1]), .i_tlast(ce_o_tlast[1]), .i_tvalid(ce_o_tvalid[1]), .i_tready(ce_o_tready[1]),
    .o_tdata(ce_i_tdata[1]), .o_tlast(ce_i_tlast[1]), .o_tvalid(ce_i_tvalid[1]), .o_tready(ce_i_tready[1]),
    .debug(ce_debug[1]));

  noc_block_duc #( .NUM_HB(2), .CIC_MAX_INTERP(128)) inst_noc_block_duc_0 (
    .bus_clk(bus_clk), .bus_rst(bus_rst),
    .ce_clk(ce_clk), .ce_rst(ce_rst),
    //.i_tdata(ce_o_tdata[2]), .i_tlast(ce_o_tlast[2]), .i_tvalid(ce_o_tvalid[2]), .i_tready(ce_o_tready[2]),
    .i_tdata(afp0_rx_tdata), .i_tlast(afp0_rx_tlast), .i_tvalid(afp0_rx_tvalid), .i_tready(afp0_rx_tready),
    .o_tdata(ce_i_tdata[2]), .o_tlast(ce_i_tlast[2]), .o_tvalid(ce_i_tvalid[2]), .o_tready(ce_i_tready[2]),
    .debug(ce_debug[2]));

  noc_block_duc #( .NUM_HB(2), .CIC_MAX_INTERP(128)) inst_noc_block_duc_1 (
    .bus_clk(bus_clk), .bus_rst(bus_rst),
    .ce_clk(ce_clk), .ce_rst(ce_rst),
    .i_tdata(ce_o_tdata[3]), .i_tlast(ce_o_tlast[3]), .i_tvalid(ce_o_tvalid[3]), .i_tready(ce_o_tready[3]),
    .o_tdata(ce_i_tdata[3]), .o_tlast(ce_i_tlast[3]), .o_tvalid(ce_i_tvalid[3]), .o_tready(ce_i_tready[3]),
    .debug(ce_debug[3]));

  // Fill remaining crossbar ports with loopback FIFOs
  genvar n;
  generate
    for (n = 4; n < NUM_CE; n = n + 1) begin
      noc_block_axi_fifo_loopback inst_noc_block_axi_fifo_loopback (
        .bus_clk(bus_clk), .bus_rst(bus_rst),
        .ce_clk(ce_clk), .ce_rst(ce_rst),
        .i_tdata(ce_o_tdata[n]), .i_tlast(ce_o_tlast[n]), .i_tvalid(ce_o_tvalid[n]), .i_tready(ce_o_tready[n]),
        .o_tdata(ce_i_tdata[n]), .o_tlast(ce_i_tlast[n]), .o_tvalid(ce_i_tvalid[n]), .o_tready(ce_i_tready[n]),
        .debug(ce_debug[n]));
    end
  endgenerate
